<script setup lang="ts">
import { useBoolean } from '@/hooks'
import mapboxgl from 'mapbox-gl'
import { URL_CONFIGS } from '@/constants'
import http from '@/utils/http'
import { GetFeaturesByGeometryParameters, FeatureService, FGBLayer } from '@supermapgis/iclient-mapboxgl'
import polygonClipping from 'polygon-clipping'

const { bool: addLoading, setTrue: startLoading, setFalse: endLoading } = useBoolean(true)

const demSource = {
  type: 'raster',
  tiles: [URL_CONFIGS.DEM_URL],
  tileSize: 256
}

const dyMapSource = {
  type: 'raster',
  tileSize: 256,
  tiles: [URL_CONFIGS.DY_MAP_URL],
  rasterSource: 'iserver'
}

const tdtVec = {
  type: 'raster',
  tiles: [URL_CONFIGS.VEC_TIANDITU_URL],
  tileSize: 256
}
const tdtCva = {
  type: 'raster',
  tiles: [URL_CONFIGS.CVA_TIANDITU_URL],
  tileSize: 256
}

onMounted(async () => {
  startLoading()
  initMap()
  await initSource()
  initQueryMap()
  setTimeout(() => endLoading(), 2000) // 延迟2秒结束 loading 动画，效果更好
})

function initMap() {
  window.map = new mapboxgl.Map({
    container: 'map',
    style: {
      version: 8,
      glyphs: '/fonts/{fontstack}/{range}.pbf',
      sources: {
        tdtVec: tdtVec,
        tdtCva: tdtCva,
        demSource: demSource,
        dyMapSource: dyMapSource
      },
      layers: [
        {
          id: 'tdtVec',
          type: 'raster',
          source: 'tdtVec',
          minzoom: 0,
          maxzoom: 22
        },
        {
          id: 'tdtCva',
          type: 'raster',
          source: 'tdtCva',
          minzoom: 0,
          maxzoom: 22
        },
        {
          id: 'dy',
          type: 'raster',
          source: 'dyMapSource',
          minzoom: 0,
          maxzoom: 22
        }
      ]
    },
    crs: 'EPSG:4490',
    center: [104.26, 30.93],
    zoom: 8
  })
  map.addControl(new mapboxgl.NavigationControl(), 'top-right')
  map.addControl(new mapboxgl.ScaleControl({}), 'bottom-left')
}

async function initSource() {
  const queryOption = {
    getFeatureMode: 'SQL',
    datasetNames: ['SiChuan:A级旅游景区名录'],
    maxFeatures: 2000,
    queryParameter: {
      attributeFilter: 'SMID>0'
    }
  }
  try {
    map.addSource('sichuan-jingdian', {
      type: 'geojson',
      data: await http.post<GeoJSON.FeatureCollection<GeoJSON.Point>>(URL_CONFIGS.JINGDIAN_DATA_URL, queryOption),
      cluster: true,
      clusterMaxZoom: 14,
      clusterRadius: 100
    })
    const scene = await map.getL7Scene()
    scene.addImage('plane', '/svg/airplane.svg')
    const element = document.querySelector('.l7-control-logo')! as HTMLElement
    element.style.display = 'none'
  } catch (error) {
    throw new Error(error instanceof Error ? error.message : '加载四川景点数据失败')
  }
}

async function initQueryMap() {
  map.on('click', async function (e: any) {
    if (map.getLayer('queryDatas')) map.removeLayer('queryDatas')
    if (map.getLayer('queryDatasouter')) map.removeLayer('queryDatasouter')
    if (map.getLayer('dy')) {
      try {
        const featureService = new FeatureService(URL_CONFIGS.DY_DATA_URL)
        const queryGeometry = {
          type: 'Feature',
          geometry: { type: 'Point', coordinates: [e.lngLat.lng, e.lngLat.lat] }
        }
        const parameters = new GetFeaturesByGeometryParameters({
          datasetNames: ['dy:区县面'],
          geometry: queryGeometry,
          spatialQueryMode: 'INTERSECT'
        })
        const [fgbServiceResult, propertiesServiceResult] = await Promise.all([
          featureService.getFeaturesByGeometry(parameters, 'FGB'),
          featureService.getFeaturesByGeometry(parameters)
        ])
        map.addLayer(
          new FGBLayer({
            url: fgbServiceResult.result.newResourceLocation,
            layerID: 'queryDatas',
            strategy: 'all',
            paint: {
              'fill-color': 'rgba(255, 0, 0, 0.6)',
              'fill-outline-color': '#2ae815'
            }
          })
        )
        if (propertiesServiceResult.result.featureCount !== 0) {
          new mapboxgl.Popup().setText(propertiesServiceResult.result.features.features[0].properties.NAME).setLngLat([e.lngLat.lng, e.lngLat.lat]).addTo(map)
        }
      } catch (error) {
        throw new Error(error instanceof Error ? error.message : '区县面数据查询失败')
      }
    }

    if (map.getLayer('chengdu@SiChuan#1_unique_(0_24)')) {
      const features = map.queryRenderedFeatures(e.point, {
        layers: ['chengdu@SiChuan#1_unique_(0_24)']
      })
      if (features.length) {
        new mapboxgl.Popup().setText(features[0].properties.区县名称).setLngLat([e.lngLat.lng, e.lngLat.lat]).addTo(map)
        const sourceFeatures = map.querySourceFeatures(features[0].source, {
          sourceLayer: features[0].sourceLayer,
          filter: ['in', 'SmID', features[0].properties.SmID]
        })
        map.getSource('highlight-feature-source').setData({
          type: 'FeatureCollection',
          features: [merge(sourceFeatures)]
        })
      } else {
        map.getSource('highlight-feature-source').setData({
          type: 'FeatureCollection',
          features: []
        })
      }
    }
  })

  function merge(inputs: any[]) {
    const filteredCoordinates = inputs.filter((i) => i.geometry.type !== 'MultiPolygon').map((i) => i.geometry.coordinates)

    const output = {
      id: inputs[0].id,
      type: inputs[0].type,
      geometry: {
        coordinates: polygonClipping.union(filteredCoordinates),
        type: 'MultiPolygon'
      },
      properties: inputs[0].properties
    }

    return output
  }

  map.on('mouseenter', 'chengdu@SiChuan#1_unique_(0_24)', function () {
    map.getCanvas().style.cursor = 'pointer'
  })

  map.on('mouseleave', 'chengdu@SiChuan#1_unique_(0_24)', function () {
    map.getCanvas().style.cursor = ''
  })
}
</script>

<template>
  <div id="map" class="mapContainer"></div>
  <Loading v-if="addLoading"></Loading>
</template>

<style scoped lang="scss">
.mapContainer {
  margin: 0;
  padding: 0;
  overflow: hidden;
  background: #fff;
  width: 100%;
  height: 100%;
  position: absolute;
}
</style>
